package core.reports;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.FontFactory;
import com.itextpdf.text.List;
import com.itextpdf.text.ListItem;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;


public class PDFBuilder implements IBuilder
{

	/** The document where the report is being printed */
	private Document document = null;
	
	/** */
	private PdfWriter writer = null;
	
	//Table stuff
	/** The current table that is being edited */
	private PdfPTable currTable = null;
	
	/** The number of columns in the currently opened table */
	private int numColsInTable = 0;
	/** The number of cells that have been inserted into this tables row */
	private int numInserted = 0;
	//----------------------
	
	//List Stuff
	/** The current list being edited. */
	private List currList = null;
	//-----------------------
	
	
	
	/** Keeps track of whether or not this 
	 * document has been completed, as defined
	 * by the 'finish()' method.
	 */
	private boolean finished = false;
	
	/** Stores the name of the file that we are outputting to. */
	private String filename;
	
	/**
	 * This creates an PDFBuilder object that
	 * will output an PDF file to the parameter
	 * filename.  When this object is created
	 * it will create the file 'filename' and
	 * keep it open until 'finish()' is called.
	 * 
	 * @param filename The name of the output file
	 * 		that will contain the output of this 
	 * 		object.
	 * @throws DocumentException 
	 * @throws FileNotFoundException 
	 */
	PDFBuilder(String filename)
	{
		finished = false;
		this.filename = filename;
		
		//open the output file
		document = new Document();
		
		try 
		{
			writer = PdfWriter.getInstance(document,  new FileOutputStream(this.filename));
		} 
		catch (Exception e) 
		{
			finished = true;
		}
		
		document.open();
	}
	
	/**
	 * Returns the name of the file that this object
	 * is outputting the data to.
	 * 
	 * @return A String that contains the filename of
	 * 		where the data is getting saved.
	 */
	public String getFileName()
	{
		return filename;
	}
	
	@Override
	public void addTitle(String title)
	{
		if (finished) return;
		
		Font font = FontFactory.getFont(FontFactory.TIMES_BOLD);
		font.setSize(24);
		
		Paragraph p = new Paragraph();
		p.setFont(font);
		p.add(title);
		p.setAlignment(Element.ALIGN_CENTER);
		
		//add it to the document
		try 
		{
			document.add(p);
		} 
		catch (DocumentException e) 
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void addParagraph(String text) 
	{
		if (finished) return;
		
		Font font = FontFactory.getFont(FontFactory.TIMES);
		font.setSize(10);
		
		Paragraph p = new Paragraph();
		p.setFont(font);
		p.add(text);
		
		//add it to the document
		try 
		{
			document.add(p);
		} 
		catch (DocumentException e) 
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void addTable(int numCols) 
	{
		if (finished) return;
		
		if (currTable != null) return;
		
		currTable = new PdfPTable(numCols);
		currTable.setWidthPercentage(100);
		numColsInTable = numCols;
		numInserted = 0;
	}

	@Override
	public void addColumnHeader(String header)
	{
		if (finished) return;
		
		if (currTable == null) return;
		
		Font font = FontFactory.getFont(FontFactory.TIMES_BOLD);
		font.setSize(12);
		
		PdfPCell newCell = new PdfPCell(new Phrase(header, font));
		
		currTable.addCell(newCell);
		
		numInserted++;
		
		if (numInserted > numColsInTable)
		{
			numInserted -= numColsInTable;
		}
	}

	@Override
	public void addCell(String data)
	{
		if (finished) return;
		
		if (currTable == null) return;
		
		Font font = FontFactory.getFont(FontFactory.TIMES);
		font.setSize(8);
		
		PdfPCell newCell = new PdfPCell(new Phrase(data, font));
		
		currTable.addCell(newCell);
		
		numInserted++;
		
		if (numInserted > numColsInTable)
		{
			numInserted -= numColsInTable;
		}
	}

	@Override
	public void closeCurrentTable() 
	{
		if (finished) return;
		
		if (currTable == null) return;
		
		for (int i = 0; i < (numColsInTable - numInserted); i++)
		{
			PdfPCell newCell = new PdfPCell(new Phrase(" "));
			newCell.setBorder(PdfPCell.NO_BORDER);
			
			currTable.addCell(newCell);
		}
		
		try 
		{
			document.add(currTable);
		} 
		catch (DocumentException e) 
		{
			e.printStackTrace();
		}
		
		currTable = null;
	}

	@Override
	public void addList() 
	{
		if (finished) return;
		
		if (currList != null) return;
		
		currList = new List(List.UNORDERED);
		
	}

	@Override
	public void addListItem(String item)
	{
		if (finished) return;
		
		if (currList == null) return;
		
		ListItem newItem = new ListItem(item);
		
		currList.add(newItem);
	}

	@Override
	public void closeCurrentList()
	{
		if (finished) return;
		
		try 
		{
			document.add(currList);
		} 
		catch (DocumentException e) 
		{
			e.printStackTrace();
		}
		
		currList = null;
	}

	@Override
	public void finish() 
	{
		if (currTable != null) closeCurrentTable();
		if (currList != null) closeCurrentList();
		
		document.close();
		finished = true;
	}

	@Override
	public void addBlankLine() 
	{
if (finished) return;
		
		Font font = FontFactory.getFont(FontFactory.TIMES);
		font.setSize(12);
		
		Paragraph p = new Paragraph();
		p.setFont(font);
		p.add(" ");
		
		//add it to the document
		try 
		{
			document.add(p);
		} 
		catch (DocumentException e) 
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void addSubTitle(String subTitle) 
	{
		if (finished) return;
		
		addBlankLine();
		
		Font font = FontFactory.getFont(FontFactory.TIMES_BOLD);
		font.setSize(18);
		
		Paragraph p = new Paragraph();
		p.setFont(font);
		p.add(subTitle);
		p.setAlignment(Element.ALIGN_LEFT);
		
		//add it to the document
		try 
		{
			document.add(p);
		} 
		catch (DocumentException e) 
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		addBlankLine();
	}

	
	
}
